# src/webui/web_admin.py

from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from pydantic import BaseModel
from typing import List, Dict, Any
import json
import os
from pathlib import Path

# Web管理应用
web_app = FastAPI(title="UBBC 规则管理系统", version="1.2")

# Jinja2 模板配置
templates = Jinja2Templates(directory="src/webui/templates")

# 挂载静态文件
web_app.mount("/static", StaticFiles(directory="src/webui/static"), name="static")

# 数据模型
class RuleModel(BaseModel):
    rule_name: str
    description: str
    keywords: List[str]

class RulesData(BaseModel):
    rules: List[RuleModel]

# 规则文件路径
RULES_FILE = "rule-definitions.json"

def load_rules() -> Dict[str, Any]:
    """加载规则数据"""
    try:
        with open(RULES_FILE, 'r', encoding='utf-8') as f:
            return json.load(f)
    except FileNotFoundError:
        return {"rules": []}
    except json.JSONDecodeError:
        raise HTTPException(status_code=500, detail="规则文件格式错误")

def save_rules(rules_data: Dict[str, Any]) -> bool:
    """保存规则数据"""
    try:
        with open(RULES_FILE, 'w', encoding='utf-8') as f:
            json.dump(rules_data, f, ensure_ascii=False, indent=4)
        return True
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"保存失败: {str(e)}")

@web_app.get("/")
async def admin_page(request: Request):
    """管理页面"""
    # 示例数据，可以从实际系统获取
    total_requests = 42
    violations_count = 3

    return templates.TemplateResponse(
        "index.html",
        {
            "request": request,
            "total_requests": total_requests,
            "violations_count": violations_count
        }
    )

# 保留旧的内联HTML路由作为备用
@web_app.get("/old", response_class=HTMLResponse)
async def admin_page_old():
    """管理页面（旧版）"""
    html_content = """
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>UBBC 规则管理系统</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
            background: #f0f2f5;
            min-height: 100vh;
            color: #262626;
            margin: 0;
            padding: 0;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 24px;
        }
        
        .header {
            text-align: center;
            color: #262626;
            margin-bottom: 32px;
            background: white;
            padding: 32px;
            border-radius: 8px;
            box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
        }
        
        .header h1 {
            font-size: 2.5rem;
            margin-bottom: 8px;
            color: #1890ff;
            font-weight: 600;
        }
        
        .header p {
            font-size: 1rem;
            color: #8c8c8c;
            margin: 0;
        }
        
        .card {
            background: white;
            border-radius: 8px;
            box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
            padding: 24px;
            margin-bottom: 24px;
            transition: box-shadow 0.3s ease;
        }
        
        .card:hover {
            box-shadow: 0 4px 12px rgba(0,0,0,0.15);
        }
        
        @keyframes fadeInUp {
            from {
                opacity: 0;
                transform: translateY(30px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }
        
        .btn {
            background: #1890ff;
            color: white;
            border: 1px solid #1890ff;
            padding: 8px 16px;
            border-radius: 6px;
            font-size: 14px;
            cursor: pointer;
            transition: all 0.3s ease;
            margin: 4px;
            height: 32px;
            line-height: 1.5;
        }
        
        .btn:hover {
            background: #40a9ff;
            border-color: #40a9ff;
            transform: translateY(-1px);
            box-shadow: 0 2px 4px rgba(24, 144, 255, 0.2);
        }
        
        .btn-danger {
            background: #ff4d4f;
            border-color: #ff4d4f;
        }
        
        .btn-danger:hover {
            background: #ff7875;
            border-color: #ff7875;
            box-shadow: 0 2px 4px rgba(255, 77, 79, 0.2);
        }
        
        .btn-success {
            background: #52c41a;
            border-color: #52c41a;
        }
        
        .btn-success:hover {
            background: #73d13d;
            border-color: #73d13d;
            box-shadow: 0 2px 4px rgba(82, 196, 26, 0.2);
        }
        
        .form-group {
            margin-bottom: 16px;
        }
        
        label {
            display: block;
            margin-bottom: 8px;
            font-weight: 500;
            color: #262626;
            font-size: 14px;
        }
        
        input, textarea {
            width: 100%;
            padding: 8px 12px;
            border: 1px solid #d9d9d9;
            border-radius: 6px;
            font-size: 14px;
            transition: all 0.3s ease;
            background: #fff;
        }
        
        input:focus, textarea:focus {
            outline: none;
            border-color: #1890ff;
            box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
        }
        
        input:hover, textarea:hover {
            border-color: #40a9ff;
        }
        
        .rule-item {
            background: #fafafa;
            border: 1px solid #f0f0f0;
            border-radius: 8px;
            padding: 16px;
            margin-bottom: 16px;
            transition: all 0.3s ease;
        }
        
        .rule-item:hover {
            border-color: #d9d9d9;
            box-shadow: 0 2px 8px rgba(0,0,0,0.09);
        }
        
        .rule-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 12px;
        }
        
        .rule-name {
            font-size: 1.1rem;
            font-weight: 500;
            color: #262626;
        }
        
        .keywords {
            display: flex;
            flex-wrap: wrap;
            gap: 8px;
            margin-top: 8px;
        }
        
        .keyword {
            background: #e6f7ff;
            color: #1890ff;
            border: 1px solid #91d5ff;
            padding: 2px 8px;
            border-radius: 4px;
            font-size: 12px;
            font-weight: 400;
        }
        
        .loading {
            text-align: center;
            padding: 40px;
            font-size: 16px;
            color: #8c8c8c;
        }
        
        .modal {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0,0,0,0.45);
            z-index: 1000;
        }
        
        .modal-content {
            background: white;
            margin: 5% auto;
            padding: 24px;
            border-radius: 8px;
            width: 90%;
            max-width: 600px;
            max-height: 80vh;
            overflow-y: auto;
            box-shadow: 0 4px 12px rgba(0,0,0,0.15);
        }
        
        .close {
            float: right;
            font-size: 24px;
            font-weight: normal;
            cursor: pointer;
            color: #8c8c8c;
            line-height: 1;
        }
        
        .close:hover {
            color: #262626;
        }
        
        .stats {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 16px;
            margin-bottom: 24px;
        }
        
        .stat-card {
            background: white;
            border: 1px solid #f0f0f0;
            padding: 24px;
            border-radius: 8px;
            text-align: center;
            transition: box-shadow 0.3s ease;
        }
        
        .stat-card:hover {
            box-shadow: 0 2px 8px rgba(0,0,0,0.09);
        }
        
        .stat-number {
            font-size: 2rem;
            font-weight: 600;
            margin-bottom: 8px;
            color: #1890ff;
        }
        
        .stat-label {
            font-size: 14px;
            color: #8c8c8c;
        }
        
        /* 测试功能样式 */
        .test-area {
            background: #f9f9f9;
            border: 2px dashed #d9d9d9;
            border-radius: 8px;
            padding: 24px;
            text-align: center;
            margin: 16px 0;
            transition: all 0.3s ease;
        }
        
        .test-area:hover {
            border-color: #1890ff;
            background: #f0f9ff;
        }
        
        .test-area.dragover {
            border-color: #1890ff;
            background: #e6f7ff;
        }
        
        .file-input {
            display: none;
        }
        
        .upload-btn {
            background: #1890ff;
            color: white;
            border: none;
            padding: 8px 16px;
            border-radius: 6px;
            cursor: pointer;
            margin: 8px;
        }
        
        .test-result {
            margin-top: 16px;
            padding: 16px;
            border-radius: 8px;
            text-align: left;
        }
        
        .test-result.compliant {
            background: #f6ffed;
            border: 1px solid #b7eb8f;
            color: #389e0d;
        }
        
        .test-result.non-compliant {
            background: #fff2f0;
            border: 1px solid #ffccc7;
            color: #cf1322;
        }
        
        .violated-rules {
            margin-top: 8px;
        }
        
        .violated-rule {
            display: inline-block;
            background: #ff4d4f;
            color: white;
            padding: 2px 8px;
            border-radius: 4px;
            font-size: 12px;
            margin: 2px;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🛡️ UBBC 规则管理系统</h1>
            <p>Universal Business Behavior Checker - Rules Management</p>
        </div>
        
        <div class="card">
            <div class="stats" id="stats">
                <!-- 统计信息将在这里显示 -->
            </div>
            
            <div style="text-align: center; margin-bottom: 30px;">
                <button class="btn" onclick="showAddModal()">➕ 添加新规则</button>
                <button class="btn btn-success" onclick="exportRules()">📥 导出规则</button>
                <button class="btn" onclick="loadRules()">🔄 刷新数据</button>
                <button class="btn" style="background: #722ed1; border-color: #722ed1;" onclick="openTestModal()">🧪 测试图片</button>
            </div>
            
            <div id="rules-container">
                <div class="loading">正在加载规则数据...</div>
            </div>
        </div>
    </div>
    
    <!-- 添加/编辑规则模态框 -->
    <div id="ruleModal" class="modal">
        <div class="modal-content">
            <span class="close" onclick="closeModal()">&times;</span>
            <h2 id="modalTitle">添加新规则</h2>
            <form id="ruleForm">
                <div class="form-group">
                    <label for="ruleName">规则名称:</label>
                    <input type="text" id="ruleName" required>
                </div>
                <div class="form-group">
                    <label for="ruleDescription">规则描述:</label>
                    <textarea id="ruleDescription" rows="3" required></textarea>
                </div>
                <div class="form-group">
                    <label for="ruleKeywords">关键词 (用逗号分隔):</label>
                    <textarea id="ruleKeywords" rows="3" placeholder="关键词1, 关键词2, 关键词3" required></textarea>
                </div>
                <div style="text-align: center;">
                    <button type="submit" class="btn btn-success">💾 保存规则</button>
                    <button type="button" class="btn" onclick="closeModal()">❌ 取消</button>
                </div>
            </form>
        </div>
    </div>
    
    <!-- 测试图片模态框 -->
    <div id="testModal" class="modal">
        <div class="modal-content">
            <span class="close" onclick="closeTestModal()">&times;</span>
            <h2>📷 测试图片合规性</h2>
            <div class="form-group">
                <label for="imageUpload">选择图片文件:</label>
                <input type="file" id="imageUpload" accept="image/*" onchange="previewImage(this)">
            </div>
            <div id="imagePreview" style="display: none; text-align: center; margin: 20px 0;">
                <img id="previewImg" style="max-width: 300px; max-height: 200px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
            </div>
            <div style="text-align: center; margin: 20px 0;">
                <button type="button" id="testBtn" class="btn btn-primary" onclick="testImage()" disabled>
                    🔍 开始检测
                </button>
                <button type="button" class="btn" onclick="closeTestModal()">❌ 取消</button>
            </div>
            <div id="testResult" class="test-result" style="display: none;"></div>
        </div>
    </div>
    
    <script>
        let currentRules = [];
        let editingIndex = -1;
        
        // 加载规则数据
        async function loadRules() {
            try {
                const response = await fetch('/api/rules');
                const data = await response.json();
                currentRules = data.rules;
                renderRules();
                updateStats();
            } catch (error) {
                console.error('加载规则失败:', error);
                document.getElementById('rules-container').innerHTML = 
                    '<div class="loading" style="color: red;">❌ 加载规则失败</div>';
            }
        }
        
        // 渲染规则列表
        function renderRules() {
            const container = document.getElementById('rules-container');
            if (currentRules.length === 0) {
                container.innerHTML = '<div class="loading">📝 暂无规则，点击上方按钮添加新规则</div>';
                return;
            }
            
            container.innerHTML = currentRules.map((rule, index) => `
                <div class="rule-item">
                    <div class="rule-header">
                        <div class="rule-name">${rule.rule_name}</div>
                        <div>
                            <button class="btn" onclick="editRule(${index})">✏️ 编辑</button>
                            <button class="btn btn-danger" onclick="deleteRule(${index})">🗑️ 删除</button>
                        </div>
                    </div>
                    <p style="color: #666; margin-bottom: 10px;">${rule.description}</p>
                    <div class="keywords">
                        ${rule.keywords.map(keyword => `<span class="keyword">${keyword}</span>`).join('')}
                    </div>
                </div>
            `).join('');
        }
        
        // 更新统计信息
        function updateStats() {
            const totalRules = currentRules.length;
            const totalKeywords = currentRules.reduce((sum, rule) => sum + rule.keywords.length, 0);
            const avgKeywords = totalRules > 0 ? (totalKeywords / totalRules).toFixed(1) : 0;
            
            document.getElementById('stats').innerHTML = `
                <div class="stat-card">
                    <div class="stat-number">${totalRules}</div>
                    <div class="stat-label">总规则数</div>
                </div>
                <div class="stat-card">
                    <div class="stat-number">${totalKeywords}</div>
                    <div class="stat-label">总关键词数</div>
                </div>
                <div class="stat-card">
                    <div class="stat-number">${avgKeywords}</div>
                    <div class="stat-label">平均关键词/规则</div>
                </div>
            `;
        }
        
        // 显示添加模态框
        function showAddModal() {
            editingIndex = -1;
            document.getElementById('modalTitle').textContent = '添加新规则';
            document.getElementById('ruleForm').reset();
            document.getElementById('ruleModal').style.display = 'block';
        }
        
        // 编辑规则
        function editRule(index) {
            editingIndex = index;
            const rule = currentRules[index];
            document.getElementById('modalTitle').textContent = '编辑规则';
            document.getElementById('ruleName').value = rule.rule_name;
            document.getElementById('ruleDescription').value = rule.description;
            document.getElementById('ruleKeywords').value = rule.keywords.join(', ');
            document.getElementById('ruleModal').style.display = 'block';
        }
        
        // 删除规则
        async function deleteRule(index) {
            if (!confirm('确定要删除这个规则吗？')) return;
            
            try {
                currentRules.splice(index, 1);
                await saveRules();
                renderRules();
                updateStats();
            } catch (error) {
                alert('删除失败: ' + error.message);
            }
        }
        
        // 关闭模态框
        function closeModal() {
            document.getElementById('ruleModal').style.display = 'none';
        }
        
        // 保存规则
        async function saveRules() {
            const response = await fetch('/api/rules', {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify({rules: currentRules})
            });
            
            if (!response.ok) {
                throw new Error('保存失败');
            }
        }
        
        // 导出规则
        function exportRules() {
            const dataStr = JSON.stringify({rules: currentRules}, null, 4);
            const dataBlob = new Blob([dataStr], {type: 'application/json'});
            const url = URL.createObjectURL(dataBlob);
            const link = document.createElement('a');
            link.href = url;
            link.download = 'rule-definitions.json';
            link.click();
            URL.revokeObjectURL(url);
        }
        
        // 表单提交处理
        document.getElementById('ruleForm').addEventListener('submit', async function(e) {
            e.preventDefault();
            
            const ruleName = document.getElementById('ruleName').value.trim();
            const ruleDescription = document.getElementById('ruleDescription').value.trim();
            const ruleKeywords = document.getElementById('ruleKeywords').value
                .split(',')
                .map(k => k.trim())
                .filter(k => k.length > 0);
            
            if (!ruleName || !ruleDescription || ruleKeywords.length === 0) {
                alert('请填写所有必填字段');
                return;
            }
            
            const newRule = {
                rule_name: ruleName,
                description: ruleDescription,
                keywords: ruleKeywords
            };
            
            try {
                if (editingIndex >= 0) {
                    currentRules[editingIndex] = newRule;
                } else {
                    currentRules.push(newRule);
                }
                
                await saveRules();
                closeModal();
                renderRules();
                updateStats();
            } catch (error) {
                alert('保存失败: ' + error.message);
            }
        });
        
        // 点击模态框外部关闭
        window.addEventListener('click', function(e) {
            const modal = document.getElementById('ruleModal');
            if (e.target === modal) {
                closeModal();
            }
            const testModal = document.getElementById('testModal');
            if (e.target === testModal) {
                closeTestModal();
            }
        });
        
        // 测试图片相关函数
        function openTestModal() {
            document.getElementById('testModal').style.display = 'block';
            resetTestModal();
        }
        
        function closeTestModal() {
            document.getElementById('testModal').style.display = 'none';
            resetTestModal();
        }
        
        function resetTestModal() {
            document.getElementById('imageUpload').value = '';
            document.getElementById('imagePreview').style.display = 'none';
            document.getElementById('testResult').style.display = 'none';
            document.getElementById('testBtn').disabled = true;
        }
        
        function previewImage(input) {
            if (input.files && input.files[0]) {
                const reader = new FileReader();
                reader.onload = function(e) {
                    document.getElementById('previewImg').src = e.target.result;
                    document.getElementById('imagePreview').style.display = 'block';
                    document.getElementById('testBtn').disabled = false;
                };
                reader.readAsDataURL(input.files[0]);
            }
        }
        
        async function testImage() {
            const fileInput = document.getElementById('imageUpload');
            const testBtn = document.getElementById('testBtn');
            const resultDiv = document.getElementById('testResult');
            
            if (!fileInput.files || !fileInput.files[0]) {
                alert('请先选择图片文件');
                return;
            }
            
            // 禁用按钮并显示加载状态
            testBtn.disabled = true;
            testBtn.innerHTML = '🔄 检测中...';
            resultDiv.style.display = 'none';
            
            try {
                const formData = new FormData();
                formData.append('file', fileInput.files[0]);
                
                const response = await fetch('http://localhost:5080/api/v1/check-image-upload', {
                    method: 'POST',
                    body: formData
                });
                
                if (!response.ok) {
                    throw new Error(`HTTP error! status: ${response.status}`);
                }
                
                const result = await response.json();
                displayTestResult(result);
                
            } catch (error) {
                resultDiv.innerHTML = `
                    <div style="color: #ff4d4f; padding: 16px; border: 1px solid #ff4d4f; border-radius: 6px; background: #fff2f0;">
                        <strong>❌ 检测失败</strong><br>
                        错误信息: ${error.message}
                    </div>
                `;
                resultDiv.style.display = 'block';
            } finally {
                // 恢复按钮状态
                testBtn.disabled = false;
                testBtn.innerHTML = '🔍 开始检测';
            }
        }
        
        function displayTestResult(result) {
            const resultDiv = document.getElementById('testResult');
            
            let html = '';
            if (result.compliant) {
                html = `
                    <div style="color: #52c41a; padding: 16px; border: 1px solid #52c41a; border-radius: 6px; background: #f6ffed;">
                        <h3 style="margin: 0 0 10px 0; color: #52c41a;">✅ 图片合规</h3>
                        <p style="margin: 0;">该图片未包含违规内容，符合平台规范。</p>
                    </div>
                `;
            } else {
                html = `
                    <div style="color: #ff4d4f; padding: 16px; border: 1px solid #ff4d4f; border-radius: 6px; background: #fff2f0;">
                        <h3 style="margin: 0 0 10px 0; color: #ff4d4f;">⚠️ 图片违规</h3>
                        <p><strong>违规原因:</strong> ${result.reason}</p>
                `;
                
                if (result.matched_rules && result.matched_rules.length > 0) {
                    html += '<p><strong>命中规则:</strong></p><ul style="margin: 5px 0 0 20px;">';
                    result.matched_rules.forEach(rule => {
                        html += `<li>${rule}</li>`;
                    });
                    html += '</ul>';
                }
                
                if (result.confidence) {
                    html += `<p><strong>置信度:</strong> ${(result.confidence * 100).toFixed(1)}%</p>`;
                }
                
                html += '</div>';
            }
            
            if (result.processing_time) {
                html += `<div style="color: #666; font-size: 12px; margin-top: 10px; text-align: center;">
                    检测耗时: ${result.processing_time.toFixed(2)}秒
                </div>`;
            }
            
            resultDiv.innerHTML = html;
            resultDiv.style.display = 'block';
        }
        
        // 页面加载时自动加载规则
        loadRules();
    </script>
</body>
</html>
    """
    return HTMLResponse(content=html_content)

@web_app.get("/api/rules")
async def get_rules():
    """获取规则数据API"""
    return load_rules()

@web_app.post("/api/rules")
async def save_rules_api(rules_data: RulesData):
    """保存规则数据API"""
    save_rules({"rules": [rule.dict() for rule in rules_data.rules]})
    return {"status": "success", "message": "规则保存成功"}

@web_app.get("/api/logs")
async def get_logs(search: str = ""):
    """获取日志数据API"""
    try:
        logs_data = []

        # 读取主日志文件
        try:
            with open("logs/ubbc.log", 'r', encoding='utf-8') as f:
                for line in f:
                    if search.lower() in line.lower():
                        logs_data.append(line.strip())
        except FileNotFoundError:
            pass

        # 读取违规日志文件
        try:
            with open("logs/violations.log", 'r', encoding='utf-8') as f:
                for line in f:
                    if search.lower() in line.lower():
                        logs_data.append(line.strip())
        except FileNotFoundError:
            pass

        return {"logs": logs_data[-100:]}  # 返回最近100条日志
    except Exception as e:
        return {"logs": [], "error": str(e)}

@web_app.get("/health")
async def health_check():
    """健康检查"""
    return {"status": "ok", "service": "UBBC Web Admin"}

if __name__ == "__main__":
    import uvicorn
    import json
    
    # 读取配置
    with open('../config.json', 'r') as f:
        config = json.load(f)
    
    web_port = int(config['server']['web-port'])
    host = config['server']['host']
    
    print(f"🚀 启动UBBC Web管理界面: http://{host}:{web_port}")
    uvicorn.run(web_app, host=host, port=web_port)
